home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / AEObject-Edition1.0.2 Sample / Publish.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-09  |  35.8 KB  |  895 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  *
  3.  *  Apple Developer Technical Support
  4.  *
  5.  *  Edition publishing routines
  6.  *
  7.  *  Program:    AEObject-Edition Sample
  8.  *  File:       Publish.c - C Source
  9.  *
  10.  *  by:         C.K. Haun <TR>
  11.  *
  12.  *  Copyright © 1990-1992 Apple Computer, Inc.
  13.  *  All rights reserved.
  14.  *
  15.  *------------------------------------------------------------------------------
  16.  * Publish handles most of the publishing housekeeping.  There is (are,am,be,whatever) 
  17.  * some routines that are common to both publishing and subscribing, they 
  18.  * are located in Subscribe.c 
  19.  *----------------------------------------------------------------------------*/
  20. #define __PUBLISH__
  21.  
  22. #pragma segment Publish
  23.  
  24.  
  25. #include "Sampdefines.h"
  26.  
  27.  
  28. /*  CreatePublisher takes the currently selected area in the current window 
  29. *       and creates an edition.  It starts by setting up some default data 
  30. *       structures and creating a preview picture.  
  31. *       Then the user is prompted for a location and name for the publisher
  32. *       with the NewPublisherDialog.  If the user clicks OK, then the edition
  33. *       is created and the section handle and rectangle for this edition is
  34. *       stored in my data structure for this window, and the first edition
  35. *       is written out.
  36. */
  37.  
  38. OSErr CreatePublisher(OSType typeToMake,Boolean fromEvent,FSSpecPtr theSpec)
  39. {
  40.  
  41.     NewPublisherReply myreply;
  42.     Handle theData;
  43.     Rect currentRect;
  44.     mySectionDataHandle pubText;
  45.     Str31 addPub;
  46.     static pubCounter;
  47.     OSErr myErr;
  48.     FSSpecPtr theOwningDoc = nil;
  49.     FSSpec tempSpec;
  50.     windowCHandle shortName;
  51.     extern Point expPoint;
  52.     extern Boolean gExpanded;
  53.     Boolean myWasChanged;
  54.     /* we're publishing from the current, topmost window */
  55.     shortName = (windowCHandle)GetWRefCon(FrontWindow());
  56.     HLock((Handle)shortName);
  57.     switch (typeToMake) {
  58.         case kGenericPICTWord:
  59.             currentRect = (*shortName)->selectionRect;
  60.             /* take the rectangle we currently have selected, and make it a picture */
  61.             theData = (Handle)MyMakePicture(¤tRect);      /* my function to make a PICT */
  62.             /* Set up the reply record for the publisher dialog.  */
  63.             myreply.usePart = false;                        /* must be false */
  64.             myreply.previewFormat = kGenericPICTWord;                 /* type of data we're publishing */
  65.             myreply.preview = theData;                      /* handle to the pict data */
  66.             break;
  67.         case kGenericTEXTWord:
  68.             /* make text preview */
  69.             myreply.usePart = false;                        /* must be false */
  70.             myreply.previewFormat = kGenericTEXTWord;                 /* type of data we're publishing */
  71.             pubText = GetTextSection(shortName, stPublisher);
  72.             HLock((Handle)pubText);
  73.             theData = (*pubText)->additionalData;                  /* duplicate the text for our preview */
  74.             HandToHand(&theData);
  75.             if (GetHandleSize(theData) > kMaxTextPreview)
  76.                 SetHandleSize(theData, kMaxTextPreview);
  77.             
  78.             myreply.preview = theData;
  79.             break;
  80.         case kCustomType:
  81.             break;
  82.     }
  83.     GetLastEditionContainerUsed(&gEdSpec);                  /* get a new edition containter.  */
  84.     /* this call gives us a duplicate of the last used, or if none used last, gives */
  85.     /* us a default container */
  86.     /* BY THE WAY - the 'last used' means the last used by the Edition Manager, not */
  87.     /* by your application, so if you don't specify a default name then the */
  88.     /* name that comes up as the default for the edition may be the last */
  89.     /* name used by another application, or from the last time your */
  90.     /* application was run.  So if you are concerned about this (like you */
  91.     /* think it may confuse the user) set your own default */
  92.     /* As a sidelight (and not guarenteed) an alias to the last edition container used */
  93.     /* is stored in the 'Preferences' folder in the system folder */
  94.     myreply.container = gEdSpec;                            /* put our file spec in the container to be filled */
  95.     /* now set the default name to be the same as the window plus a count */
  96.     GetWTitle(FrontWindow(), &myreply.container.theFile.name);
  97.     GetIndString(addPub, kGeneralStrings, kDotPub);
  98.     AppendString(myreply.container.theFile.name, addPub);
  99.     NumToString((long)((*shortName)->numPubs) + 1, addPub);
  100.     AppendString(myreply.container.theFile.name, addPub);
  101.     if(!fromEvent){
  102.     if (!gExpanded)
  103.         myErr = NewPublisherDialog(&myreply);               /* run the dialog */
  104.     else
  105.         myErr = NewPublisherExpDialog(&myreply, expPoint, kExpandedDITL, (ExpDlgHookProcPtr)ExpOptHook,
  106.                                       (ExpModalFilterProcPtr)ExpOptFilter, nil);
  107.     if (myErr) {
  108.         ShowMe("\pPubisher dialog", myErr,__LINE__);
  109.         return(myErr);
  110.     }
  111.     if (myreply.canceled) {                                 /* they canceled.  release memory, reset our */
  112.         /* menus and cursors, and go away */
  113.         switch (typeToMake) {
  114.             case kGenericPICTWord:
  115.                 KillPicture((PicHandle)theData);
  116.                 InvalRect(&(*shortName)->selectionRect);
  117.                 gShowPub = false;
  118.                 (*shortName)->hasSelection = false;
  119.                 SetMyCursor(0);
  120.                 SwitchChecks(kSelectStuff);
  121.                 
  122.                 break;
  123.             case kGenericTEXTWord:
  124.                 DisposHandle((*pubText)->additionalData);
  125.                 DisposHandle((Handle)pubText);
  126.                 DisposHandle(theData);
  127.                 break;
  128.             case kCustomType:
  129.                 break;
  130.         }
  131.         return(userCanceledErr);
  132.     }}
  133.     /* They clicked Publish.  First create the container (file) to hold the data */
  134.     /* See if thye are replacing a file */
  135.     if (!myreply.replacing) {
  136.         /* If we were given a spec by the event, the put that file in */
  137.         if(theSpec)myreply.container.theFile=*theSpec;
  138.         if (myErr = CreateEditionContainerFile(&myreply.container.theFile, kMySignature, myreply.container.theFileScript)) {
  139.             ShowMe("\pCreateEditionContainerFIle", myErr,__LINE__);
  140.             return(myErr);
  141.         } 
  142.         } else {
  143.         /* they agreed to delete an existing file.  Kill it. */
  144.         FSpDelete(&myreply.container.theFile);
  145.         if (myErr = CreateEditionContainerFile(&myreply.container.theFile, kMySignature, myreply.container.theFileScript)) {
  146.             ShowMe("\pCreateEditionContainerFIle", myErr,__LINE__);
  147.             return(myErr);
  148.  
  149.         }
  150.     }
  151.     /* now create the section record to describe this data to the edition manager */
  152.     /*  The section handle that is returned by this function will be the */
  153.     /* way that you will reference this edition for as long as the edition is */
  154.     /* active. */
  155.     /* The main way you'll keep track is through the section ID number. */
  156.     /* In this case, I have a base ID number for the window, and I just increment */
  157.     /* my general ID (gSectionID) every time I create an edition, and add it to the window ID.  */
  158.     if (GetHandleSize((Handle)(*shortName)->fileAliasHandle) == 0) {
  159.         myErr = NewSection(&myreply.container, nil, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave, &gSecHandle);
  160.         /* nil for sectionDocument if it's never been saved */
  161.     } else {
  162.         /* if the file has been saved once, then we can store a reference to the 'parent' file */
  163.         /* in the edition */
  164.  
  165.  
  166.         myErr = ResolveAlias(nil, ((*shortName)->fileAliasHandle), &tempSpec, &myWasChanged);
  167.         myErr = NewSection(&myreply.container, &tempSpec, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave,
  168.                            &gSecHandle);
  169.         theOwningDoc=&tempSpec;
  170.     }
  171.         if (!myErr) {
  172.         /* put the section handle into our window structure */
  173.         (*gSecHandle)->refCon = kNeverSaved;                /*            meaning that this _document_ has not been saved */
  174.         /* put what type of thing this is in the refcon of the section handle */
  175.         switch (typeToMake) {
  176.             /* This is a little kludgy because I want to */
  177.             case kGenericPICTWord:
  178.                 (*gSecHandle)->refCon = kPictType;
  179.                 break;
  180.             case kGenericTEXTWord:
  181.                 (*gSecHandle)->refCon = kTextType;
  182.                 break;
  183.         }
  184.         StorePublisher(shortName, gSecHandle, &(*shortName)->selectionRect, pubText, typeToMake);
  185.     
  186.     /* now write the data to the container */
  187.     /* first make a spec from the saved alias, if there is one */
  188.     MyWriteSection(gSecHandle, theData, typeToMake,theOwningDoc);
  189.      } else {
  190.         /* error creating the section */
  191.         ShowMe("\p Couldn't create section", myErr,__LINE__);    
  192.     }
  193.     HUnlock(theData);
  194.     switch (typeToMake) {
  195.         case kGenericPICTWord:
  196.             KillPicture((PicHandle)theData);
  197.             break;
  198.         case kGenericTEXTWord:
  199.             break;
  200.         case kCustomType:
  201.             break;
  202.     }
  203.    
  204.     (*shortName)->hasSelection = false;
  205.     InvalRect(&(*shortName)->selectionRect);                /* get rid of border once publish has happened */
  206.     gShowPub = false;
  207.     (*shortName)->hasSelection = false;
  208.     SetMyCursor(0);
  209.     SwitchChecks(kSelectStuff);
  210.     HUnlock((Handle)shortName);
  211. }
  212.  
  213. /* end CreatePublisher */
  214.  
  215. /* MyUpdateEdition publishes the latest data for this edition.  This will
  216. * be called when the user selects 'Send Edition Now' from the options
  217. * dialog, or when the document is saved (if automatic saving is 
  218. * enabled), or if a section write AppleEvent happens
  219. */
  220. OSErr MyUpdateEdition(SectionHandle theSection)
  221. {
  222.     WindowPtr tempWindow;
  223.     Boolean tempSub, tempPub;
  224.     Boolean wasChanged;
  225.     windowCHandle shortName;
  226.     SectionHandle *tempPtr;
  227.     FSSpecPtr theOwningDoc=nil;
  228.     FSSpec owner;
  229.     register qq;
  230.     Rect *tempRectPtr;
  231.     extern Rect gShowPubRect;
  232.     extern Rect gShowSubRect;
  233.     WindowPtr owningWindow = FindSection(theSection);
  234.  
  235.     GetPort(&tempWindow);
  236.     shortName = (windowCHandle)GetWRefCon(owningWindow);
  237.     HLock((Handle)shortName);
  238.     if(GetHandleSize((Handle)(*shortName)->fileAliasHandle)){
  239.     ResolveAlias(nil,(*shortName)->fileAliasHandle,&owner,&wasChanged);
  240.     theOwningDoc=&owner;
  241.     }
  242.     if (((*theSection)->refCon & 0xf) == kPictType) {
  243.         HLock((Handle)theSection);
  244.         /* kill the borders, if any are showing right now */
  245.         tempSub = gShowSub;
  246.         tempPub = gShowPub;
  247.         if (gShowSub)
  248.             InvalRect(&gShowSubRect);
  249.         if (gShowPub)
  250.             InvalRect(&gShowPubRect);
  251.         gShowSub = gShowPub = false;
  252.         SetPort(owningWindow);
  253.         (ProcPtr)((*shortName)->drawMe)(shortName, owningWindow);     /* draw without borders */
  254.         /* 
  255.         /* search this window for the section asked for */
  256.         HLock((*shortName)->pubs);
  257.         tempPtr = (SectionHandle *)*(*shortName)->pubs;
  258.         for (qq = 0; qq < (*shortName)->numPubs; qq++) {
  259.             HLock((Handle)*tempPtr);
  260.             if ((*theSection)->sectionID == (*(*tempPtr))->sectionID) {
  261.                 PicHandle tempPic;
  262.                 /* it's this one, grab the rect, pic it, publish it, and go away */
  263.                 HLock((*shortName)->pubRects);
  264.                 tempRectPtr = (Rect *)*(*shortName)->pubRects;
  265.                 tempRectPtr += qq;
  266.                 tempPic = MyMakePicture(tempRectPtr);
  267.                 HUnlock((*shortName)->pubRects);
  268.                 MyWriteSection(*tempPtr, (Handle)tempPic, kGenericPICTWord,theOwningDoc);
  269.                 KillPicture(tempPic);
  270.                 HUnlock((Handle)*tempPtr);
  271.                 break;
  272.             }
  273.         }
  274.         HUnlock((Handle)theSection);
  275.         HUnlock((Handle)shortName);
  276.     } else {
  277.         mySectionDataHandle theTS = TextSectionFromSecHandle(theSection);
  278.         /* it's a text pub */
  279.         MyWriteSection(theSection, (*theTS)->additionalData, kGenericTEXTWord,theOwningDoc);
  280.         
  281.     }
  282.     InvalRect(&owningWindow->portRect);
  283.     SetPort(tempWindow);
  284.     return(noErr);
  285. }
  286.  
  287. /* end MyUpdateEdition */
  288.  
  289. /* MyMakePicture is a handy place to create our PICT demo data item.
  290. * It's called to create the actual edition data as well as the 'preview'
  291. * picture.
  292. */
  293. PicHandle MyMakePicture(Rect *thisRect)
  294. {
  295.     PicHandle thepic;
  296.     windowCHandle drawers;
  297.     Boolean tempPub, tempSub;
  298.     RgnHandle tempClip;
  299.     /* make sure borders aren't included in the picture */
  300.     tempPub = gShowPub;
  301.     tempSub = gShowSub;
  302.     gShowPub = false;
  303.     gShowSub = false;
  304.     tempClip = NewRgn();
  305.     GetClip(tempClip);
  306.     ClipRect(thisRect);
  307.     thepic = OpenPicture(thisRect);
  308.     drawers = (windowCHandle)GetWRefCon(FrontWindow() );
  309.     HLock((Handle)drawers);
  310.     (ProcPtr)((*drawers)->drawMe)(drawers, FrontWindow() );
  311.     HUnlock((Handle)drawers);
  312.     ClosePicture();
  313.     SetClip(tempClip);
  314.     DisposeRgn(tempClip);
  315.     /* restore old border states */
  316.     gShowPub = tempPub;
  317.     gShowSub = tempSub;
  318.     return(thepic);
  319. }
  320.  
  321. /* end MyMakePicture */
  322.  
  323. /* AEWriteSectionHandler is the AppleEvent handler for section write
  324. * events.   It first pulls the SectionHandle out of the AppleEvent record,
  325. * then verifies that this is a registered section (still active, not canceled)
  326. * and then calls MyUpdateEdition to write the edition
  327. */
  328. pascal OSErr AEWriteSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  329. {
  330. #pragma unused (reply,refIn)
  331.     SectionHandle theSection;
  332.     OSErr myErr;
  333.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  334.  
  335.     if (myErr = IsRegisteredSection((SectionHandle)theSection)) {
  336.         ShowMe("\p Write IsRegisteredSection", myErr,__LINE__);
  337.         return(myErr);
  338.     }
  339.     MyUpdateEdition(theSection);
  340.     
  341. }
  342.  
  343. /* end AEWriteSectionHandler */
  344. /* ••••• REVISED!  This event has been revised since it's initial release */
  345. /* to reflect the final definition of this event, and the object that it accepts  */
  346. /* as a parameter */
  347. /* •••• NEW EVENT •••• */
  348. /* •• Please read the description and code in the Inside Mac vol VI chapters on */
  349. /* the Edition Manager and APpleEvents for a full description */
  350. /* AECreatePubHandler handles the new create publisher event */
  351.  
  352. pascal OSErr AECreatePubHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  353. {
  354. #pragma unused (reply,refIn)
  355.  
  356. windowCHandle tempWC;
  357. OSErr myErr = noErr;
  358. Size returnedSize;
  359. long savedStart,savedEnd;
  360. Rect savedRect;
  361. DescType returnedType = typeNull;
  362. OSType theType;
  363. AEDesc returnedToken;
  364. AEDesc theObject;
  365. FSSpec theFSSpec;
  366. FSSpecPtr theFSS = nil;
  367. CTextObjHandle cTextBack;
  368. CWordObjHandle cWordBack;
  369. CShapeObjHandle cShapeback;
  370.  
  371. WindowPtr containingWindow;
  372. WindowPtr oldFront=nil;
  373. theObject.descriptorType = typeNull;
  374. returnedToken.descriptorType = typeNull;
  375. oldFront = FrontWindow();
  376. /* this event has two parameters, a object specifier and an alias handle. */
  377. /* Both parameters are optional. */
  378. /* if the object doesn't exsist, then we publish the current selection */
  379. /* if the alias doesn't exsist, then we put up the options dialog */
  380. AEGetKeyDesc(messagein,keyDirectObject,typeObjectSpecifier,&theObject);
  381. /* the AEM has a built-in coercion from alias to FSSpec */
  382. AEGetKeyPtr(messagein,keyAEEditionFileLoc,typeAlias,&returnedType,(Ptr)&theFSSpec,sizeof(FSSpec),&returnedSize);
  383. if(typeFSS == returnedType)
  384.     theFSS = &theFSSpec;
  385.  
  386. /* checking for null instead of for an error 
  387. because I don't care if either of these error out, I just care if they return a descriptor 
  388. or not.  Which I could do with two error variables, but you know.... */
  389. /* Now resolve the object I got (if I got one)  */
  390. if(theObject.descriptorType != typeNull) 
  391.     myErr = AEResolve(&theObject, kAEIDoMinimum, &returnedToken);
  392.  
  393. if(!myErr){
  394. /* so the action, will be something like this, since I am but a lowly  */
  395. /* example program */
  396. /* if the value returned from AEResolve is a graphic-type thing, I will put it's */
  397. /* rectangle into the current selection, and call CreatePub. */
  398. /* if it's a text thing, I will save the current selection, reset the selction, and */
  399. /* call CreatePub.  I'm typing this in as a comment because I don't know if I'll */
  400. /* get it implemented within my release timeframe, but that is the idea. */
  401. /* Also, because of the way I initially designed this program, the publisher must */
  402. /* be the front window.  Not a good idea, I will re-write that in a future release, */
  403. /* but for now we live with it. */
  404.     switch(returnedToken.descriptorType){
  405.     /* get the owning window */
  406.     case cText:
  407.     theType = kGenericTEXTWord;
  408.     cTextBack = (CTextObjHandle)returnedToken.dataHandle;
  409.     containingWindow=(*cTextBack)->theOwningWindow;
  410.     tempWC = (windowCHandle)GetWRefCon(containingWindow);
  411.     /* save off current  */
  412.     savedStart = (*(*tempWC)->boxHandle)->selStart;
  413.     savedEnd=(*(*tempWC)->boxHandle)->selEnd;
  414.     /* and since they asked for the whole text, make the end equal the beginning */
  415.     (*(*tempWC)->boxHandle)->selEnd = (*(*tempWC)->boxHandle)->teLength;
  416.     (*(*tempWC)->boxHandle)->selStart=0;
  417.     /* and do the thing */
  418.     SelectWindow(containingWindow);
  419.     
  420.     myErr = CreatePublisher(theType,true,theFSS);
  421.     /* restore */
  422.     (*(*tempWC)->boxHandle)->selStart = savedStart;
  423.     (*(*tempWC)->boxHandle)->selEnd = savedEnd;
  424.  
  425.  
  426.     break;
  427.     
  428.     case cWord:
  429.     theType = kGenericTEXTWord;
  430.     cWordBack = (CWordObjHandle)returnedToken.dataHandle;
  431.     containingWindow=(*cWordBack)->theOwningWindow;
  432.     tempWC = (windowCHandle)GetWRefCon(containingWindow);
  433.     savedStart = (*(*tempWC)->boxHandle)->selStart;
  434.     savedEnd=(*(*tempWC)->boxHandle)->selEnd;
  435.     (*(*tempWC)->boxHandle)->selStart = (*cWordBack)->startPos;
  436.     (*(*tempWC)->boxHandle)->selEnd = (*cWordBack)->endPos;
  437.     /* do the thing */
  438.     SelectWindow(containingWindow);
  439.  
  440.     myErr = CreatePublisher(theType,true,theFSS);
  441.     (*(*tempWC)->boxHandle)->selStart = savedStart;
  442.     (*(*tempWC)->boxHandle)->selEnd = savedEnd;
  443.     break;
  444.     case cGraphicLine:
  445.     case cRectangle:
  446.     case cOval:
  447.     theType = kGenericPICTWord;
  448.     /* save the current selection rect if any */
  449.     cShapeback = (CShapeObjHandle)returnedToken.dataHandle;
  450.     containingWindow=(*cShapeback)->theOwningWindow;
  451.     tempWC = (windowCHandle)GetWRefCon(containingWindow);
  452.     savedRect=(*tempWC)->selectionRect;
  453.     (*tempWC)->selectionRect = (*(*cShapeback)->theShape)->theRect;
  454.     SelectWindow(containingWindow);
  455.  
  456.     myErr = CreatePublisher(theType,true,theFSS);
  457.     (*tempWC)->selectionRect = savedRect; 
  458.     break;
  459.     default:
  460.     myErr = errAEEventNotHandled;    /* I don't know how to publish this object */
  461.     break;
  462.     }
  463. } else {
  464. /* Here, there was an object, but I couldn't understand it.  That is an _error_ */
  465. /* condition, which is different from no object being available */
  466.  
  467. myErr= errAENoSuchObject;
  468. }
  469.  
  470. /* if there was an old front window, make it frontmost agin */
  471. if(oldFront)ChangePlane(oldFront);
  472. return(myErr);
  473. }
  474. /* end AECreatePubHandler */
  475.  
  476.  
  477.  
  478. /* AEScrollSectionHandler handles the scroll section event.  You'll get this
  479. * event when the user clicks 'Open Publisher' either from the 
  480. * Subcriber Options dialog, or from the Finder window.
  481. * This may also have happened after an ODOC AppleEvent, so 
  482. * don't assume anything about your state that wouldn't be true 
  483. * after an initial application launch
  484. */
  485. pascal OSErr AEScrollSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  486. {
  487. #pragma unused (reply,refIn)
  488.     WindowPtr tempWindow;
  489.     SectionHandle theSection;
  490.     OSErr myErr;
  491.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  492.     tempWindow = FindSection(theSection);
  493.     /* First bring our application to the front, then */
  494.     /* treat this the same way you would a click in a back window */
  495.  
  496.     myErr=AEInteractWithUser(kAEDefaultTimeout,nil,(IdleProcPtr) CommonIdleFunction);
  497.     if(!myErr)SetFrontProcess(&gOurSN);
  498.         else ShowMe("\ptheEr",myErr,__LINE__);
  499.     if (tempWindow != nil)
  500.         ChangePlane(tempWindow);
  501.     return(noErr);
  502. }
  503.  
  504. /* end AEScrollSectionHandler */
  505.  
  506. /* AECancelSectionHandler cancels a current section, either a publisher
  507. * or subscriber.  This function pulls the section handle out of the 
  508. * AppleEvent, then dispatches to the proper cancel routine for a
  509. * pub or sub.
  510. */
  511. pascal OSErr AECancelSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  512. {
  513. #pragma unused (reply,refIn)
  514.     SectionHandle theSection;
  515.     OSErr myErr;
  516.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  517.     myErr = IsRegisteredSection(theSection);
  518.     if (myErr != noErr)
  519.         return(myErr);                                      /* already killed by someone */
  520.     MyCancelSection(theSection, FindSection(theSection));
  521.     
  522. }
  523.  
  524. /* end AECancelSectionHandler */
  525.  
  526. /* MyWriteSection actually opens and writes the section data.  This will
  527. * be called in response to a click in 'Send Edition Now' in the pub options
  528. * box, from the section event 'write section', or when the file is being saved
  529. * and 'pumAuto' is enabled
  530. */
  531. OSErr MyWriteSection(SectionHandle secHandle, Handle theData, OSType theType,FSSpecPtr inSpec)
  532. {
  533.     OSErr myErr;
  534.     /* update the time in the section handle please */
  535.     /* this tells the Edition Manager that the eidtion has changed, and */
  536.     /* to alert all the subscribers to the change */
  537.  
  538.     SpinCursor();
  539.     HLock((Handle)secHandle);
  540.     GetDateTime(&(*secHandle)->mdDate);                     /* ••• Please see NOTE in main.c about mdDate (find mdDate) */
  541.     HUnlock((Handle)secHandle);
  542.     /* OpenNewEdition, _NOT_ OpenEdition.  You need to use OpenNewEdition */
  543.     /* to get write access and to let the Edition Manager determine if you */
  544.     /* are allowed to write to this section */
  545.     myErr = OpenNewEdition(secHandle, kMySignature,inSpec, &gEdRefNum);
  546.     if (myErr)
  547.         ShowMe("\pOpenNewEdition", myErr,__LINE__);
  548.     HLock(theData);
  549.     /* And actually write the data (finally) */
  550.     SpinCursor();
  551.     myErr = WriteEdition(gEdRefNum, theType, *theData, GetHandleSize(theData));
  552.     if (myErr)
  553.         ShowMe("\pWriteEdition", myErr,__LINE__);
  554.     if (myErr)
  555.         myErr = 0;
  556.     else
  557.         myErr = -1;
  558.     /* The Boolean tells the Edition Manager if you were successful in */
  559.     /* writing the data. */
  560.     myErr = CloseEdition(gEdRefNum, (Boolean)myErr);
  561.             if(myErr)ShowMe("\pCloseEdition", myErr,__LINE__);
  562.     return(myErr);
  563. }
  564.  
  565. /* end MyWriteSection */
  566.  
  567. /* StorePublisher moves the window data struct storing function to here */
  568. /* shortName is locked on entry */
  569. void StorePublisher(windowCHandle shortName, SectionHandle storeSection, Rect *inRect, mySectionDataHandle textIn, OSType typeIn)
  570. {
  571.     Rect *tempRectPtr;
  572.     SectionHandle *tempPtr;
  573.     OSErr myErr;
  574.     switch (typeIn) {
  575.         case kGenericPICTWord:
  576.             HUnlock((*shortName)->pubs);
  577.             MySetHandleSize((*shortName)->pubs, GetHandleSize((*shortName)->pubs) + sizeof(Handle));
  578.             myErr = MemError();
  579.             if (myErr)
  580.                 ShowMe("\pMemory", myErr,__LINE__);
  581.             HLock((*shortName)->pubs);
  582.             tempPtr = (SectionHandle *)((*(*shortName)->pubs) + (sizeof(Handle) * ((*shortName)->numPubs)));
  583.             *tempPtr = (SectionHandle)storeSection;
  584.             /* •••• NOTE, please look at the note in the Subscribe.c file concerning the dirty flag and  */
  585.             /* editions.  Open Subscribe.c and find the string 'Human Interface' */
  586.             /*    (*shortName)->windowDirty = true;  */
  587.             /* save the rectangle to show the published rectangle if the user wants to see it. */
  588.             HUnlock((*shortName)->pubRects);
  589.             MySetHandleSize((*shortName)->pubRects, (GetHandleSize((*shortName)->pubRects) + sizeof(Rect)));
  590.             myErr = MemError();
  591.             if (myErr)
  592.                 ShowMe("\pMemory", myErr,__LINE__);
  593.             HLock((*shortName)->pubRects);
  594.             tempRectPtr = (Rect *)*(*shortName)->pubRects;
  595.             tempRectPtr += (*shortName)->numPubs;
  596.             *tempRectPtr = *inRect;
  597.             (*shortName)->numPubs++;
  598.             HUnlock((*shortName)->pubRects);
  599.             HUnlock((*shortName)->pubs);
  600.             break;
  601.         case kGenericTEXTWord:
  602.             /* set my text section ID to the same as the actual section ID, again, it keeps */
  603.             /* dereferencing down */
  604.             (*textIn)->theID = (*storeSection)->sectionID;
  605.             /* tell myself that this is a publisher */
  606.             (*textIn)->publishing = true;
  607.             if ((*shortName)->textSections == nil) {
  608.                 (*shortName)->textSections = textIn;
  609.             } else {
  610.                 mySectionDataHandle tempTS = (*shortName)->textSections;
  611.                 while ((*tempTS)->nextSection != nil) {
  612.                     tempTS = (*tempTS)->nextSection;
  613.                 }
  614.                 (*tempTS)->nextSection = textIn;
  615.             }
  616.             (*textIn)->theSection = storeSection;
  617.             break;
  618.     }
  619.     gSectionID++;
  620. }
  621.  
  622. /* Find Section returns the window that this section is included in */
  623. /* Need to look in both the PICT and TEXT lists */
  624. WindowPtr FindSection(SectionHandle inSection)
  625. {
  626.      long subIDtofind;
  627.     Boolean secFound = false;
  628.     SectionHandle *tempPtr;
  629.     SectionRecord *tempRecord;
  630.     Handle tempHandle;
  631.     WindowPtr tempNextWindow;
  632.     register jj;
  633.     subIDtofind = (*inSection)->sectionID;
  634.     tempNextWindow = mWindList;  /* start at the beginning of the chain */
  635.     while(tempNextWindow){
  636.     if (((WindowPeek)tempNextWindow)->windowKind == kDocumentWindow){ /* the clipboard is not publishing */
  637.         windowCHandle tempWC;
  638.         /* do housekeeping to get to the section handle list */
  639.         tempWC = (windowCHandle)GetWRefCon(tempNextWindow);
  640.         HLock((Handle)tempWC);
  641.         if (((*inSection)->refCon & 0xf) == kPictType) {
  642.             tempHandle = (*tempWC)->pubs;                   /* handle containing SectionHandles */
  643.             HLock(tempHandle);
  644.             tempPtr = (SectionHandle *)*tempHandle;
  645.             /* Loop through all our sections until we find this edition */
  646.             for (jj = 0; jj < (*tempWC)->numPubs; jj++) {
  647.                 HLock((Handle)*tempPtr);
  648.                 tempRecord = *(*tempPtr);
  649.                 if (tempRecord->sectionID == subIDtofind) {
  650.                     HUnlock((Handle)*tempPtr);
  651.                     HUnlock((Handle)tempWC);
  652.                     return(tempNextWindow);
  653.                 } else {
  654.                     HUnlock((Handle)tempWC);
  655.                     HUnlock((Handle)*tempPtr);
  656.                     tempPtr += 1;
  657.                 }
  658.             }
  659.             HUnlock(tempHandle);
  660.             /* same thing for subscribers */
  661.             tempHandle = (*tempWC)->subs;                   /* handle containing SectionHandles */
  662.             HLock(tempHandle);
  663.             tempPtr = (SectionHandle *)*tempHandle;
  664.             /* Loop through all our sections until we find this edition */
  665.             for (jj = 0; jj < (*tempWC)->numSubs; jj++) {
  666.                 HLock((Handle)*tempPtr);
  667.                 tempRecord = *(*tempPtr);
  668.                 if (tempRecord->sectionID == subIDtofind) {
  669.                     HUnlock((Handle)*tempPtr);
  670.                     HUnlock((Handle)tempWC);
  671.                     return(tempNextWindow);
  672.                 } else {
  673.                     HUnlock((Handle)tempWC);
  674.                     HUnlock((Handle)*tempPtr);
  675.                     tempPtr += 1;
  676.                 }
  677.             }
  678.             HUnlock(tempHandle);
  679.         } else {
  680.             /* Look in the TEXT lists */
  681.             if ((*tempWC)->textSections) {
  682.                 mySectionDataHandle tempTS = (*tempWC)->textSections;
  683.                 do {
  684.                     if ((*((*tempTS)->theSection))->sectionID == subIDtofind) {
  685.                         HUnlock((Handle)tempWC);
  686.                         return(tempNextWindow);
  687.                     }
  688.                     tempTS = (*tempTS)->nextSection;
  689.                 } while (tempTS);
  690.                 
  691.             }
  692.         }
  693.         tempNextWindow = (WindowPtr)((WindowPeek)tempNextWindow)->nextWindow; 
  694.         
  695.         HUnlock((Handle)tempWC);
  696.         }    /* if document */
  697.         tempNextWindow = (WindowPtr) ((WindowPeek)tempNextWindow)->nextWindow;
  698.     } /* while windows */
  699.     return(nil);
  700. }
  701.  
  702. pascal short ExpOptHook(short itemOffset, short itemHit, DialogPtr theDialog, Ptr yourDataPtr)
  703. {
  704.  #pragma unused (yourDataPtr)
  705.      short myHit;
  706.     short itemType;
  707.     ControlHandle theButton;
  708.     Rect theRect;
  709.     /* first make sure that a sub-dialog is not frontmost */
  710.     /* so we don't filter keys or hits to a sub-dialog */
  711.     if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon || GetWRefCon((WindowPtr)theDialog) == emOptionsDialogRefCon) {
  712.         /* only have one item in this expansion, but we'll check the range anyway */
  713.         myHit = itemHit - itemOffset;                       /* since our item numbers are relative to the total number */
  714.         /* of items in the dialog, and the system may change.  Always do your item numbering based */
  715.         /* on the offset, this will prevent incompatability when the system dialog grows or shrinks */
  716.         if (myHit == 1) {                                   /* I only added one item, so this be the one */
  717.             /* Pass itemHit here, not myHit, since the dialog manager has no idea that this is an */
  718.             /* additive dialog.  It is counting from the actual start of the DITL, not the start of */
  719.             /* your custom items */
  720.             GetDItem(theDialog, itemHit, &itemType, (Handle *)&theButton, &theRect);
  721.             if (GetCtlValue(theButton))
  722.                 SetCtlValue(theButton, false);
  723.             else
  724.                 SetCtlValue(theButton, true);
  725.         }
  726.     }
  727.     return(itemHit);                                        /* the return value must be absolute */
  728. }
  729.  
  730. pascal Boolean ExpOptFilter(DialogPtr theDialog, EventRecord *theEvent, short itemOffset, short *itemHit, Ptr yourDataPtr)
  731. {
  732. #pragma unused (itemHit,yourDataPtr)
  733.     short itemType;
  734.     ControlHandle theButton;
  735.     Rect theRect;
  736.     /* first make sure that a sub-dialog is not frontmost */
  737.     /* so we don't filter keys or hits to a sub-dialog */
  738.     if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon || GetWRefCon((WindowPtr)theDialog) == emOptionsDialogRefCon) {
  739.         /* standard filter proc kinda stuff here */
  740.         if ((theEvent->what) == keyDown) {
  741.             char tempChar;
  742.             tempChar = theEvent->message & charCodeMask;
  743.             
  744.             if (((tempChar == 'A') || (tempChar == 'a')) && (theEvent->modifiers & cmdKey)) {
  745.                 /* they pressed an A with the command key down, we get to handle it. */
  746.                 GetDItem(theDialog, itemOffset + 1, &itemType, (Handle *)&theButton, &theRect);
  747.                 if (GetCtlValue(theButton))
  748.                     SetCtlValue(theButton, false);
  749.                 else
  750.                     SetCtlValue(theButton, true);
  751.                 
  752.                 return(true);                               /* tell folks we handled it */
  753.             }
  754.         }
  755.     }
  756.     return(false);                                          /* was not a keystroke we wanted */
  757.     
  758. }
  759.  
  760. /* shortName is locked on entry */
  761. mySectionDataHandle GetTextSection(windowCHandle shortName, SectionType what)
  762. {
  763.     CharsHandle theRawText;
  764.     TEHandle tempTE;
  765.     mySectionDataHandle theTextSection;
  766.     Handle theSelection;
  767.     theTextSection = (mySectionDataHandle)NewHandle(sizeof(mySectionData));
  768.     HLock((Handle)theTextSection);
  769.     (*theTextSection)->bordered = gShowingAll;              /* create section reflecting current */
  770.     /* global border state */
  771.     tempTE = (*shortName)->boxHandle;
  772.     (*theTextSection)->startChar = (*tempTE)->selStart;
  773.     if (what == stPublisher) {
  774.         /* initialize it if it's a publisher */
  775.         (*theTextSection)->endChar = (*tempTE)->selEnd;
  776.         
  777.         theRawText = TEGetText(tempTE);
  778.         theSelection = NewHandle(((*tempTE)->selEnd) - ((*tempTE)->selStart));
  779.         
  780.         HLock(theSelection);
  781.         HLock((Handle)theRawText);
  782.         BlockMove((Ptr)*theRawText + (*tempTE)->selStart, (Ptr)*theSelection, (*tempTE)->selEnd - (*tempTE)->selStart);
  783.         HUnlock(theSelection);
  784.         HUnlock((Handle)theRawText);
  785.         (*theTextSection)->additionalData = theSelection;
  786.     } else {
  787.         /* set start same as end for subscribers */
  788.         (*theTextSection)->endChar = (*tempTE)->selStart;
  789.         (*theTextSection)->additionalData = NewHandle(0);
  790.     }
  791.     (*theTextSection)->nextSection = nil;
  792.     return(theTextSection);
  793. }
  794.  
  795. mySectionDataHandle TextSectionFromSecHandle(SectionHandle theSection)
  796. {
  797.     windowCHandle tempWC = (windowCHandle)GetWRefCon(FindSection(theSection));      /* gets the window it's in */
  798.     mySectionDataHandle tempTS = (*tempWC)->textSections;
  799.     unsigned long idToFind;
  800.     
  801.     idToFind = (*theSection)->sectionID;
  802.     /* find the ID that matches this thang */
  803.     do {
  804.         if ((*tempTS)->theID == idToFind)
  805.             return(tempTS);
  806.         tempTS = (*tempTS)->nextSection;
  807.     } while (tempTS);
  808.     return(nil);                                            /* failed */
  809. }
  810.  
  811. /* In SearchPubs we'll search the publishers in this window for a publisher */
  812. /* that was clicked in.  If we find one, hilite it and outline it. */
  813. /* Point is already in local coordinates */
  814. Boolean SearchPubs(Point thePoint)
  815. {
  816.     register qq;
  817.     Rect rectToCheck;
  818.     Rect cornerRect;
  819.     Rect *theRects;
  820.     Str63 pubString;
  821.     Boolean gotIt = false;
  822.     windowCHandle shortname = (windowCHandle)GetWRefCon(FrontWindow());
  823.     HLock((Handle)shortname);
  824.     if ((*shortname)->numPubs) {                            /* does this window have any publishers? */
  825.         /* yes, see if one was clicked in */
  826.         HLock((*shortname)->pubRects);                      /* lock the rect handle down */
  827.         theRects = (Rect *)*(*shortname)->pubRects;
  828.         /* dereference it and cast it to a rect pointer so checking will be 
  829.         *   conceptually easier (i.e. you can read it) 
  830.         */
  831.         for (qq = 0; qq < (*shortname)->numPubs; qq++) {        /* step through 'em */
  832.             SectionHandle *tempPtr;
  833.             rectToCheck = *theRects;
  834.             if (PtInRect(thePoint, &rectToCheck)) {         /* thePoint is coming from your */
  835.                 /* last event record */
  836.                 /* We've found a section that has been clicked in */
  837.                 if (gShowPub && (rectToCheck != gShowPubRect))
  838.                     InvalRect(&gShowPubRect);               /* clear previous, if there was one */
  839.                 gShowPub = true;
  840.                 if (gShowSub) {/* clear previous, if there was one */
  841.                     InsetRect(&gShowSubRect, -4, -4);
  842.                     InvalRect(&gShowSubRect);
  843.                     InsetRect(&gShowSubRect, 4, 4);
  844.  
  845.                     gShowSub = false;
  846.                 }
  847.                 /* make sure the border gets draw next update */
  848.                 InsetRect(&rectToCheck,-4,-4);
  849.                 InvalRect(&rectToCheck);
  850.                 InsetRect(&rectToCheck,4,4);
  851.                 /* we've found it with it's rectangle, so now dig out the */
  852.                 /* section handle */
  853.                 HLock((*shortname)->pubs);
  854.                 tempPtr = (SectionHandle *)*(*shortname)->pubs;
  855.                 tempPtr += qq;
  856.                 /* and move the section handle into our global variable that */
  857.                 /* contains the currently highlighted section, so we can */
  858.                 /* access it from the Options function and dialog */
  859.                 gShowingSecHandle = *tempPtr;
  860.                 /* done with the pointer handle */
  861.                 HUnlock((*shortname)->pubs);
  862.                 /* change the menu item name now */
  863.                 GetIndString(pubString, kGeneralStrings, kPubOptString);
  864.                 
  865.                 SetItem(gEditMenuHandle, kSoptionsItem,pubString);
  866.                 gShowPubRect = rectToCheck;
  867.                 gotIt = true;
  868.                 /* Now we need to stretch the thing if the user wants too */
  869.                 /* See if it was in the corner rect first */
  870.                 cornerRect = gShowPubRect;
  871.                 cornerRect.top = cornerRect.bottom - 7;
  872.                 cornerRect.left = cornerRect.right - 7;
  873.                 if (PtInRect(thePoint, &cornerRect)) {
  874.                     PullRect(shortname, &gShowPubRect, false, true,true);
  875.                     if (*theRects != gShowPubRect) {
  876.                         *theRects = gShowPubRect;
  877.                         InvalRect(theRects);
  878.                     }
  879.                 }
  880.             }
  881.             if (gotIt)
  882.                 break;
  883.             theRects++;                                     /* increase by one Rect */
  884.         }
  885.         HUnlock((*shortname)->pubRects);
  886.     }
  887.     HUnlock((Handle)shortname);
  888.     return(gotIt);
  889. }
  890.  
  891. /* end SearchPubs */
  892.  
  893.  
  894. #undef __PUBLISH__
  895.